#include "stdafx.h"
#include "YNetworkFactory.h"
#include "YTcpClientSession.h"
#include "YTcpServerSession.h"
#include "YUdpSession.h"
#include <YSimpleSystem/YSimpleSystem.h>

namespace ysimple_network
{

	YNetworkFactory::YNetworkFactory()
	{
		m_tasks.run([&](){

			while(1)
			{
				DisconnectedSocketDesc disconnectedSocket = m_Time_Wait_State_Pool.dequeue();

				if (disconnectedSocket.m_socket == INVALID_SOCKET)
				{				
					break;
				}

				const DWORD reusableTime = 40*1000;

				DWORD64 tick = ::GetTickCount();
				if (tick - disconnectedSocket.m_disconnectedTick < reusableTime)
				{
					Sleep((DWORD)(reusableTime-(tick - disconnectedSocket.m_disconnectedTick)+50));	
					DWORD64 endTick = ::GetTickCount();
				}				

				m_clientSockets.push(disconnectedSocket.m_socket);
			}

		});
	}


	TCP_SESSION_SPTR YNetworkFactory::createProactiveClientTCPSession(ysimple_system::IProactor& proactor)
	{
		SOCKET socket = INVALID_SOCKET;
		bool reusedSocket = m_clientSockets.try_pop(socket);
		if (reusedSocket == false)
		{
			socket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);
		}
		
		return TCP_SESSION_SPTR(
			new YTcpClientSession(proactor, socket, reusedSocket, 
			[&](ITCPSession* ptr)
			{
				ysimple_system::OutputDebugString("\nreleaseProactiveClientSession(%0x, %d)", ptr, ptr->getSocket());
				m_Time_Wait_State_Pool.enqueue(DisconnectedSocketDesc(ptr->getSocket()));	
			})
			
		);
	}

	TCP_SESSION_SPTR YNetworkFactory::createProactiveServerTCPSession(ysimple_system::IProactor& proactor)
	{	
		SOCKET socket = INVALID_SOCKET;
		bool reusedSocket = m_serverSockets.try_pop(socket);
		if (reusedSocket == false)
		{
			socket = WSASocket(AF_INET,SOCK_STREAM,IPPROTO_IP,NULL,0,WSA_FLAG_OVERLAPPED);
		}

		return TCP_SESSION_SPTR(new YTcpServerSession(proactor, socket, reusedSocket, 
			[&](ITCPSession* ptr)
			{	
				m_serverSockets.push(ptr->getSocket());
			})
		);
	}

	ysimple_network::PACKET_SPTR YNetworkFactory::createPacket( size_t len )
	{
		return PACKET_SPTR(
			new YPacket(len),
			[](YPacket* ptr)
		{
			delete ptr;
		}
		);
	}

	ysimple_network::UDP_SESSION_SPTR YNetworkFactory::createProactiveUDPSession( ysimple_system::IProactor& proactor )
	{
		SOCKET socket = INVALID_SOCKET;
		bool reusedSocket = m_udpSockets.try_pop(socket);
		if (reusedSocket == false)
		{
			socket = WSASocket(AF_INET,SOCK_DGRAM, IPPROTO_UDP,NULL,0,WSA_FLAG_OVERLAPPED);
		}

		return UDP_SESSION_SPTR(new YUdpSession(proactor, socket, reusedSocket, 
			[&](IUDPSession* ptr)
		{	
			m_udpSockets.push(ptr->getSocket());
		})
			);
	}

}
